using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gj.Galaxy.Logic;
using Gj.Galaxy.Network;
using ILRuntime.Runtime;

namespace Gj.ILRuntimeExt.Adapt
{
    //这个类就是继承适配器类
    public class DefineLoadResourceAdapter : CrossBindingAdaptor
    {
        public override Type BaseCLRType
        {
            get
            {
                //如果你是想一个类实现多个Unity主工程的接口，这里需要return null;
                return typeof(DefineLoadResource);//这是你想继承的那个类
//                return null;
            }
        }

        public override Type[] BaseCLRTypes
        {
            get
            {
                //跨域继承只能有1个Adapter，因此应该尽量避免一个类同时实现多个外部接口，
                //ILRuntime虽然支持同时实现多个接口，但是一定要小心这种用法，使用不当很容易造成不可预期的问题
                //日常开发如果需要实现多个DLL外部接口，请在Unity这边先做一个基类实现那些个接口，然后继承那个基类
                //如需一个Adapter实现多个接口，请用下面这行
//                return new Type[] { typeof(BaseUISystem), typeof(UISystem), typeof(GameBeforeListener) };
                return null;
            }
        }

        public override Type AdaptorType
        {
            get
            {
                return typeof(Adaptor);//这是实际的适配器类
            }
        }

        public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
        {
            return new Adaptor(appdomain, instance);//创建一个新的实例
        }

        //实际的适配器类需要继承你想继承的那个类，并且实现CrossBindingAdaptorType接口
        public class Adaptor : DefineLoadResource, CrossBindingAdaptorType
        {
            ILTypeInstance instance;
            ILRuntime.Runtime.Enviorment.AppDomain appdomain;
            //缓存这个数组来避免调用时的GC Alloc

            private IMethod mLoadResource;
            private bool mLoadResourceGot;
            
            object[] param2 = new object[2];
            public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
            {
                this.appdomain = appdomain;
                this.instance = instance;
            }

            public ILTypeInstance ILInstance { get { return instance; } }

            public void LoadResource(string name, byte[] data)
            {
                if (!mLoadResourceGot)
                {
                    mLoadResource = instance.Type.GetMethod("LoadResource", 2);
                    mLoadResourceGot = true;
                }

                param2[0] = name;
                param2[1] = data;
                if (mLoadResource != null)
                    appdomain.Invoke(mLoadResource, instance, param2);
            }
        }
    }
}
